#include "nnslitetest.h"
#include "nnslitememory.h"
#include "nnsliteheapfile.h"
#include "nnslitebufferedheapfile.h"
#include "nnsliteobjectcontainer.h"

static f64 nnslitetest_1_distfunc(const nnsliteObject* object1, const nnsliteObject* object2)
{
	s32 f1 = *(s32*)(object1->data);
	s32 f2 = *(s32*)(object2->data);
	return (f64)abs(f1-f2);
}

static nnsliteObject nnslitetest_1_createObj(s32 value, u64 id)
{
	nnsliteObject obj;
	nnsliteObjectInit(&obj);

	obj.size = sizeof(s32);
	obj.data = nnsliteMAlloc(sizeof(s32));
	*(s32*)obj.data = value;
	obj.id = id;
	return obj;
}

NNSLITE_RET nnslitetest_1()
{
	s32 ret;
	nnsliteStore store;
	nnsliteObject obj1;
	nnsliteObject obj2[5];
	nnsliteParameters params;
	FILE* fp;
	u32 i;

	fp = fopen("nnslitetest_1.txt","w");
	memset(&params, 0, sizeof(nnsliteParameters));
	strcpy(params.filename, "nnslitetest_1.bin");
	strcpy(params.name,"nnslitetest_1");
	params.containerMaxCount = 64;
	params.distFunc = nnslitetest_1_distfunc;
	params.heapFSBufSize = 12;
	params.heapFSFileCount = 64;
	params.heapFSPageSize = 1024;
	params.heapFSNumPages = 1024;
	params.mtreeMaxDepth = 6;
	params.mtreeMaxNumNodes = 64;
	params.mtreeChildCount = 4;
	ret = nnsliteStoreCreate(&store, &params);
	if(NNSLITE_FAILED(ret))
	{
		printf("Cannot create the store : nnslitetest_1 \n");
		return -1;
	}

	for (i=0;i<32;i++)
	{
		obj1 = nnslitetest_1_createObj(10+i, 100+i);
		nnsliteStoreInsert(&store, &obj1);
		nnsliteObjectFree(&obj1);
		nnsliteStorePrint(&store,fp);
		fprintf(fp,"================time %d=================\n",i);
		fflush(fp);
	}

	nnsliteStorePrint(&store,fp);

	for (i=0;i<5;i++)
		nnsliteObjectInit(&obj2[i]);

	obj1 = nnslitetest_1_createObj(107, 107);
	nnsliteStoreNNSearch(&store, &obj1, 5, obj2);
	nnsliteObjectFree(&obj1);

	for (i=0;i<5;i++)
	{
		fprintf(fp,"%lld ",obj2[i].id);
		nnsliteObjectFree(&obj2[i]);
	}
	fprintf(fp,"\n");
	

	nnsliteStoreClose(&store);

	fclose(fp);
	printf("Test 1 over!\n");
	return NNSLITE_RET_OK;
}

/* test the heap file system*/
NNSLITE_RET nnslitetest_2()
{
	NNSLITE_RET ret;
	nnsliteHeapFS* heapFS;
	nnsliteHeapFile* hf;
	char buf[]="Hello world! N-Neigborhood Search Engine!\n";
	char outbuf[64];
	/* Create a heap file system */
	ret=nnsliteHeapFSOpenNew(&heapFS,"test_heapfile.bin",8,8,16,12);
	NNSLITE_ON_FAILED_RETURN(ret);
	/* Create a heap file */
	ret=nnsliteHeapFileOpenNew(heapFS,&hf, U32_NULL);
	NNSLITE_ON_FAILED_RETURN(ret);
	/* Write some data  */
	nnsliteHeapFileAppend(hf, buf, strlen(buf)+1);
	nnsliteHeapFileRead(hf, 3, outbuf,12);
	nnsliteHeapFileClose(hf);
	outbuf[12]=0;
	printf("outbuf = %s\n", outbuf);
	/* Close the heap file system */
	nnsliteHeapFSClose(heapFS);

	printf("Test 2 over!\n");
	return NNSLITE_RET_OK;
}

/* test the buffered heap file system*/
NNSLITE_RET nnslitetest_3()
{
	NNSLITE_RET ret;
	nnsliteHeapFS* heapFS;
	nnsliteBufferedHeapFile bhf1, bhf2;
	char buf[]="Hello world! N-Neigborhood Search Engine!\n";
	char outbuf[64];

	/* Create a heap file system */
	ret=nnsliteHeapFSOpenNew(&heapFS,"test_bufferedheapfile.bin",8,8,16,12);
	NNSLITE_ON_FAILED_RETURN(ret);
	/* Create a buffered heap file */
	ret=nnsliteBufferedHeapFileOpenNew(heapFS, &bhf1, 8, U32_NULL);
	NNSLITE_ON_FAILED_RETURN(ret);
	nnsliteBufferedHeapFileWrite(&bhf1, buf, strlen(buf)+1);
	ret=nnsliteBufferedHeapFileOpenNew(heapFS, &bhf2, 8, U32_NULL);
	NNSLITE_ON_FAILED_RETURN(ret);
	nnsliteBufferedHeapFileWrite(&bhf2, buf+6, strlen(buf+6)+1);

	nnsliteBufferedHeapFileBeginRead(&bhf1);
	nnsliteBufferedHeapFileRead(&bhf1, outbuf, 12);
	nnsliteBufferedHeapFileClose(&bhf1);
	nnsliteBufferedHeapFileClose(&bhf2);
	outbuf[12]=0;
	printf("outbuf1 = %s\n", outbuf);
	/* Close the heap file system */
	nnsliteHeapFSClose(heapFS);

	/* Create a heap file system */
	ret=nnsliteHeapFSOpenNew(&heapFS,"test_bufferedheapfile.bin",8,8,16,12);
	NNSLITE_ON_FAILED_RETURN(ret);
	/* Create a buffered heap file */
	ret=nnsliteBufferedHeapFileOpenNew(heapFS, &bhf1, 4*1024, U32_NULL);
	NNSLITE_ON_FAILED_RETURN(ret);
	/* Write some data  */
	nnsliteBufferedHeapFileWrite(&bhf1, buf, strlen(buf)+1);
	nnsliteBufferedHeapFileBeginRead(&bhf1);
	nnsliteBufferedHeapFileRead(&bhf1, outbuf, 12);
	nnsliteBufferedHeapFileClose(&bhf1);
	outbuf[12]=0;
	printf("outbuf2 = %s\n", outbuf);
	/* Close the heap file system */
	nnsliteHeapFSClose(heapFS);
	
	printf("Test 3 over!\n");
	return NNSLITE_RET_OK;
}

NNSLITE_RET nnslitetest_4(void)
{
	return NNSLITE_RET_OK;
}

NNSLITE_RET nnslitetest_5(void)
{
	s32 ret;
	nnsliteStore store;
	nnsliteObject obj1;
	nnsliteParameters params;
	FILE* fp;
	u32 i;

	/* Create the store */
	memset(&params, 0, sizeof(nnsliteParameters));
	strcpy(params.filename, "nnslitetest_5.bin");
	strcpy(params.name,"nnslitetest_5");
	params.containerMaxCount = 64;
	params.distFunc = nnslitetest_1_distfunc;
	params.heapFSBufSize = 12;
	params.heapFSFileCount = 64;
	params.heapFSPageSize = 1024;
	params.heapFSNumPages = 1024;
	params.mtreeMaxDepth = 6;
	params.mtreeMaxNumNodes = 64;
	params.mtreeChildCount = 4;
	ret = nnsliteStoreCreate(&store, &params);
	if(NNSLITE_FAILED(ret))
	{
		printf("Cannot create the store : nnslitetest_1 \n");
		return -1;
	}

	/* Insert the objects */
	for (i=0;i<32;i++)
	{
		obj1 = nnslitetest_1_createObj(10+i, 100+i);
		nnsliteStoreInsert(&store, &obj1);
		nnsliteObjectFree(&obj1);
	}
	
	/* Close the store */
	ret = nnsliteStoreClose(&store);
	
	/* Open the store */
	ret = nnsliteStoreOpen(&store,"nnslitetest_5.bin",nnslitetest_1_distfunc);
	NNSLITE_ON_FAILED_RETURN(ret);

	fp = fopen("nnslitetest_5.txt","w");
	nnsliteStorePrint(&store,fp);

	/* Close the store and log file */
	ret = nnsliteStoreClose(&store);
	NNSLITE_ON_FAILED_RETURN(ret);
	fclose(fp);

	return NNSLITE_RET_OK;
}

